import CodeView from '../../../shared/components/CodeView';
import CodeBlock from '../../../shared/components/CodeBlock';
import Example from '../../../shared/components/Example';
import Blockquote from '../../../shared/components/Blockquote';
import InlineFragment from '../../../shared/components/InlineFragment';
import { BaseMenu, SubHeader, IconLeft, DoubleIcon, IconRight, ActionOverflow, OverflowMenu, NotificationsMenu } from '../menus/dropdown/example';
import * as DropdownHeight from '../menus/dropdown-height/example';
import { Submenu } from '../menus/submenu/example';
import { DoctypeIcon } from '../icons/doctype/example';
import { getDisplayElementById } from '../../shared/helpers';

<div className="doc lead">
  A Menu offers a list of actions or functions that a user can access.
</div>

<CodeView exampleOnly demoStyles="height: 150px;">
  <IconLeft hasLeftIcon />
</CodeView>

## About Menu

The unordered menu list `<ul>` with `role="menu"` should be contained in a `<div>` with the class `.slds-dropdown`.

The target HTML element and dropdown need to be wrapped in the class `.slds-dropdown-trigger dropdown-trigger_click`.

### Accessibility

#### Markup

- The menu trigger is a focusable element (`<a>` or `<button>`) with `aria-haspopup="true"`
- The menu trigger has the `aria-expanded` attribute applied and the value is set to `"true"` or `"false"` depending on if the menu is open or not.
- The menu has `role="menu"` and an `aria-label` attribute whose value is the name of the menu trigger
- The menu items have `role="menuitem"`, `role="menuitemcheckbox"`, or `role="menuitemradio"`, depending on the selection options

#### Keyboard Interactions

The main thing that distinguishes menus from other popover blocks is keyboard navigation: elsewhere, users press the Tab key to navigate through actionable items, but in a menu, users press the arrow keys to navigate.

- Arrow keys cycle focus through menu items (including disabled menu items)
- If a menu item opens a submenu, pressing Enter or the right arrow key opens the submenu and focus goes to the first item in the submenu
- If a submenu is open, pressing the left arrow key closes the submenu and puts focus back on the menu item that opened the submenu
- Tab key closes the menu and moves focus to the next focusable element on the page
- Esc key closes the menu and moves focus back to the menu trigger
- Any character key moves focus to the next menu item that starts with that character, if applicable

## Base

<Example title="Menu Base">
  <CodeView demoStyles="height: 200px;">
    <BaseMenu className="slds-dropdown_left" />
  </CodeView>
</Example>

## With Subheaders

<Blockquote type="a11y" header="Accessibility Note">
  <p>
    The <code>role="group"</code> on nested <code>&lt;ul&gt;</code> elements groups subheadings with their submenu items and 
    the <code>aria-labelledby</code> attribute on these nested <code>&lt;ul&gt;</code> elements references the <code>id</code> of the 
    corresponding subheading.
    A subheading must have <code>role="presentation"</code> on the{' '}
    <code>&lt;li&gt;</code> and the content inside the <code>&lt;li&gt;</code>{' '}
    should be in a <code>&lt;span&gt;</code>.
  </p>
</Blockquote>

<CodeBlock toggleCode={false}>
  <li
    className="slds-dropdown__header slds-truncate"
    title="Menu Sub Heading"
    role="presentation"
  >
    <span>Menu Sub Heading</span>
  </li>
</CodeBlock>

<Example title="Menu with Subheaders">
  <CodeView demoStyles="height: 300px;">
    <SubHeader />
  </CodeView>
</Example>

## With Icons

Icons can be included on either the left, right, or both sides of an option.

<Blockquote type="a11y" header="Accessibility Note">
  <p>
    If using one of the icons to indicate selection (e.g. checkmarks), be sure
    to check out the{' '}
    <a href="#With-Selectable-Items">Menus with Selectable Items</a> docs for
    the Accessibility implications.
  </p>
</Blockquote>

### Icon on the Left

<Example title="Menu with Icon Left">
  <CodeView demoStyles="height: 150px;">
    <IconLeft hasLeftIcon />
  </CodeView>
</Example>

### Icon on the Right

<Example title="Menu with Icon Right">
  <CodeView demoStyles="height: 150px;">
    <IconRight />
  </CodeView>
</Example>

### Double Icon

<Blockquote type="a11y" header="Accessibility Note">
  <p>
    If using one of the icons to indicate selection (e.g. checkmarks), be sure
    to check out the{' '}
    <a href="#With-Selectable-Items">Menus with Selectable Items</a> docs.
  </p>
</Blockquote>

<Example title="Menu with Double Icon">
  <CodeView demoStyles="height: 150px;">
    <DoubleIcon />
  </CodeView>
</Example>

## With Selectable Items

When creating a menu with selectable items:

- All selectable items need the proper role, either `role="menuitemcheckbox"` or `role="menuitemradio"`
- All selectable items should contain an icon
- Each icon must have the class `slds-icon_selected` on the `<svg>`
  - This hides icons of non-selected items
- Items that have been selected need `aria-checked="true"` on the `<a>` element

<Blockquote type="a11y" header="Revealing Icons for Selected Items">
  <p>
    A selected item reveals its icon when the class{' '}
    <code>slds-is-selected</code> is applied to the <code>&lt;li&gt;</code> and{' '}
    <code>aria-checked="true"</code> is applied to its{' '}
    <code>menuitemcheckbox</code> or <code>menuitemradio</code> child.
  </p>
</Blockquote>

<CodeBlock toggleCode={false}>
  <li className="slds-dropdown__item slds-is-selected" role="presentation">
    <a role="menuitemcheckbox" aria-checked="true">
      ...
    </a>
  </li>
</CodeBlock>

<Example title="Menu with Selectable Icon Left">
  <CodeView demoStyles="height: 150px;">
    <IconLeft isSelectable />
  </CodeView>
</Example>

## With Status Notifications

<CodeView demoStyles="height: 250px;">
  <NotificationsMenu />
</CodeView>

To enable menu items to reflect status level notifications like Error, Success and Warning, place a modifier class onto the `menuitem` that has the offending notification.

The class is based on the `slds-has-${level}` pattern, where `${level}` corresponds to the level you wish to set.

- `slds-has-error`
- `slds-has-success`
- `slds-has-warning`

<CodeBlock toggleCode={false}>
  <a
    className="slds-has-warning"
    href="#"
    onClick={e => e.preventDefault()}
    role="menuitem"
    tabIndex="-1"
  >
    ...
  </a>
</CodeBlock>

<Blockquote type="note" header="Warning Icon">
  <p>
    For warning level menu items it is required that you switch the icon to use
    the <code>currentColor</code> variant for icons.
  </p>
</Blockquote>

## With Overflow Scrolling

<Example title="Menu with Overflow Scrolling">
  <CodeView demoStyles="height: 220px;">
    <OverflowMenu className="slds-dropdown_left slds-dropdown_length-5" />
  </CodeView>
</Example>

To force overflow scrolling after either 5, 7, or 10 items, add the modifier `slds-dropdown_length-*` to the `<div>` with class `slds-dropdown` where the `*` is either 5, 7, or 10.

<CodeBlock toggleCode={false}>
  <div className="slds-dropdown slds-dropdown_length-5">...</div>
</CodeBlock>

### Scrolling for Menu Items with Icons

To force overflow scrolling after either 5, 7, or 10 items with icons, add the modifier `slds-dropdown_length-with-icon-*` to the `<div>` with class `slds-dropdown` where the `*` is either 5, 7, or 10.

<CodeView demoStyles="height: 250px;">
  <OverflowMenu
    isSelectable
    isSelected="true"
    className="slds-dropdown_left slds-dropdown_length-with-icon-5"
  />
</CodeView>

## With a Submenu

To create a menu with a submenu, add the `slds-has-submenu` class to the list item, `<li>`, that will open the submenu.

<Blockquote type="a11y" header="Accessibility Note">
  <p>
    Any menu item that opens a submenu must have <code>aria-haspop="true"</code>{' '}
    on the <code>&lt;a&gt;</code> within the <code>&lt;li&gt;</code>. In order
    to open the submenu, set <code>aria-expanded</code> to <code>true</code> on
    that <code>&lt;a&gt;</code> when the user clicks or hovers over the list
    item, or presses enter while focused on the list item. Additionally, the
    submenu should have <code>role="menu"</code> and an <code>aria-label</code>{' '}
    attribute whose value matches the name of the <code>&lt;li&gt;</code> that
    opened the submenu.
  </p>
</Blockquote>

<CodeBlock toggleCode={false}>
  <li className="slds-dropdown__item slds-has-submenu" role="presentation">
    <a
      role="menuitem"
      href="#"
      onClick={e => e.preventDefault()}
      aria-haspopup="true"
      aria-expanded="true"
      tabIndex="-1"
    >
      ...
    </a>
    <div className="slds-dropdown slds-dropdown_submenu slds-dropdown_submenu-left">
      <ul
        className="slds-dropdown__list"
        role="menu"
        aria-label="Name of Item that Opened this Menu"
      >
        ...
      </ul>
    </div>
  </li>
</CodeBlock>

### Submenu to Right

To open the submenu to the right of the main menu, add `slds-dropdown_submenu-right` to the `<div>` with the `slds-dropdown_submenu` class.

<Example title="Menu with Submenu Right">
  <CodeView demoStyles="height: 300px;">
    <Submenu ariaExpanded parentIsOpen />
  </CodeView>
</Example>

### Submenu to Left

To open the submenu to the left, add `slds-dropdown_submenu-left` to the `<div>` with the `slds-dropdown_submenu` class.

<Example title="Menu with Submenu Left">
  <CodeView demoStyles="height: 300px; margin-left: 150px;">
    <Submenu ariaExpanded parentIsOpen submenuClassnames="slds-dropdown_submenu-left" />
  </CodeView>
</Example>

## Overflow Menu with Actions

For an overflow of action items, use the overflow menu with actions styling by adding the modifier `slds-dropdown_actions` to the `div` with class `slds-dropdown`. This pattern is typically used in conjunction with a button group.

<Example title="Menu with Action Overflow">
  <CodeView demoStyles="height: 150px;">
    <ActionOverflow isOpen />
  </CodeView>
</Example>

## Positioning

There are 3 options for the positioning of the menu dropdown -- left, right, and bottom. To access these options, add a modifier to the `<div>` with class name `slds-dropdown`. For the standard positioning where the dropdown aligns with the left side of the dropdown trigger, use `slds-dropdown_left`, as seen above.

<CodeBlock toggleCode={false}>
  <div className="slds-dropdown slds-dropdown_left">...</div>
</CodeBlock>

### Positioned Right

To position the dropdown to align with the right of the dropdown trigger, use `slds-dropdown_right`.

<Example title="Menu Positioned Right">
  <CodeView demoStyles="height: 200px; margin-left: 90px;">
    <BaseMenu className="slds-dropdown_right" />
  </CodeView>
</Example>

### Positioned Bottom

To position the dropdown to sit on top of the dropdown trigger, use `slds-dropdown_bottom`.

<Example title="Menu Positioned Bottom">
  <CodeView demoStyles="margin-left: 45px; margin-top: 163px;">
    <BaseMenu className="slds-dropdown_bottom" />
  </CodeView>
</Example>

## Width

To adjust the width of the menu dropdown add modifier `slds-dropdown_*` to the `<div>` with class `slds-dropdown` where the `*` is `xx-small`, `x-small`, `small`, `medium`, or `large`.

<CodeBlock toggleCode={false}>
  <div className="slds-dropdown slds-dropdown_left slds-dropdown_medium">
    ...
  </div>
</CodeBlock>

| Modifier                                     | Example                                                                                                                 |
| -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `.slds-dropdown_xx-small` <br/> 6rem / 96px  | <div style={{height: '200px', width: '320px'}}><BaseMenu className="slds-dropdown_left slds-dropdown_xx-small" /></div> |
| `.slds-dropdown_x-small` <br/> 12rem / 192px | <div style={{height: '200px', width: '320px'}}><BaseMenu className="slds-dropdown_left slds-dropdown_x-small" /></div>  |
| `.slds-dropdown_small` <br/> 15rem / 240px   | <div style={{height: '200px', width: '320px'}}><BaseMenu className="slds-dropdown_left slds-dropdown_small" /></div>    |
| `.slds-dropdown_medium` <br/> 20rem / 320px  | <div style={{height: '200px', width: '320px'}}><BaseMenu className="slds-dropdown_left slds-dropdown_medium" /></div>   |
| `.slds-dropdown_large` <br/> 25rem / 400px   | <div style={{height: '200px', width: '320px'}}><BaseMenu className="slds-dropdown_left slds-dropdown_large" /></div>    |

## Height

To adjust the length of visible menu dropdown items before overflow scrolling activates, add modifier `slds-dropdown_length-*`, or when using icons, `slds-dropdown_length-with-icon-*`, where the `*` is `5`, `7`, `10`. Apply the height classes to both the `<div>`s with class `slds-dropdown` and `slds-dropdown__list`

<CodeBlock toggleCode={false}>
  <div className="slds-dropdown slds-dropdown_left slds-dropdown_length-7">
    <ul class="slds-dropdown__list slds-dropdown_length-7">...</ul>
  </div>
</CodeBlock>

| Modifier                                            | Example                                                                                                                                                                  |
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `.slds-dropdown_length-5` <br/> 5 items             | <div style={{height: '16rem', width: '320px'}}><InlineFragment fragmentChildren={ getDisplayElementById(DropdownHeight.states, 'dropdown-menu-length-5') }/></div>       |
| `.slds-dropdown_length-7` <br/> 7 items             | <div style={{height: '21rem', width: '320px'}}><InlineFragment fragmentChildren={ getDisplayElementById(DropdownHeight.states, 'dropdown-menu-length-7') }/></div>       |
| `.slds-dropdown_length-10` <br/> 10 items           | <div style={{height: '26rem', width: '320px'}}><InlineFragment fragmentChildren={ getDisplayElementById(DropdownHeight.states, 'dropdown-menu-length-10') }/></div>      |
| `.slds-dropdown_length-with-icon-5` <br/> 5 items   | <div style={{height: '16rem', width: '320px'}}><InlineFragment fragmentChildren={ getDisplayElementById(DropdownHeight.states, 'dropdown-menu-length-5-icon') }/></div>  |
| `.slds-dropdown_length-with-icon-7` <br/> 7 items   | <div style={{height: '21rem', width: '320px'}}><InlineFragment fragmentChildren={ getDisplayElementById(DropdownHeight.states, 'dropdown-menu-length-7-icon') }/></div>  |
| `.slds-dropdown_length-with-icon-10` <br/> 10 items | <div style={{height: '28rem', width: '320px'}}><InlineFragment fragmentChildren={ getDisplayElementById(DropdownHeight.states, 'dropdown-menu-length-10-icon') }/></div> |
